package com.atguigu.srb.core.service.impl;

import com.atguigu.common.exception.Assert;
import com.atguigu.common.result.ResponseEnum;
import com.atguigu.srb.core.enums.LendStatusEnum;
import com.atguigu.srb.core.enums.TransTypeEnum;
import com.atguigu.srb.core.hfb.FormHelper;
import com.atguigu.srb.core.hfb.HfbConst;
import com.atguigu.srb.core.hfb.RequestHelper;
import com.atguigu.srb.core.mapper.*;
import com.atguigu.srb.core.pojo.bo.TransFlowBO;
import com.atguigu.srb.core.pojo.entity.Lend;
import com.atguigu.srb.core.pojo.entity.LendItem;
import com.atguigu.srb.core.pojo.entity.UserInfo;
import com.atguigu.srb.core.pojo.vo.InvestVo;
import com.atguigu.srb.core.service.LendItemService;
import com.atguigu.srb.core.service.LendService;
import com.atguigu.srb.core.service.TransFlowService;
import com.atguigu.srb.core.service.UserAccountService;
import com.atguigu.srb.core.util.LendNoUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 标的出借记录表 服务实现类
 * </p>
 *
 * @author Bright
 * @since 2022-04-09
 */
@Service
@Slf4j
public class LendItemServiceImpl extends ServiceImpl<LendItemMapper, LendItem> implements LendItemService {

    @Resource
    LendMapper lendMapper;
    @Resource
    UserAccountService userAccountService;
    @Resource
    UserAccountMapper userAccountMapper;
    @Resource
    UserBindMapper userBindMapper;
    @Resource
    UserInfoMapper userInfoMapper;
    @Resource
    LendService lendService;

    @Resource
    TransFlowService transFlowService;


    @Override
    public String commitInvest(InvestVo investVo) {

        //投资用户id
        Long userId = investVo.getInvestUserId();
        //必须为投资人投资
        UserInfo userInfo = userInfoMapper.selectById(userId);
        Assert.isTrue(userInfo.getUserType() == 1, ResponseEnum.ERROR);
        Lend lend = lendMapper.selectById(investVo.getLendId());
        //标的状态必须为募资中
        Assert.isTrue(lend.getStatus().equals(LendStatusEnum.INVEST_RUN.getStatus()), ResponseEnum.LEND_FULL_SCALE_ERROR);
        // 标的不能超卖
        BigDecimal investAmount = investVo.getInvestAmount();
        BigDecimal addAmount = investAmount.add(lend.getInvestAmount());
        BigDecimal amount = lend.getAmount();
        Assert.isTrue(addAmount.compareTo(amount) <= 0, ResponseEnum.LEND_FULL_SCALE_ERROR);
        // 账户可用余额充足
        BigDecimal account = userAccountService.getAccountByUserId(userId);
        Assert.isTrue(investAmount.compareTo(account) <= 0, ResponseEnum.NOT_SUFFICIENT_FUNDS_ERROR);

        //生成投资项
        LendItem lendItem = new LendItem();
        //生成投资编号
        String lendItemNo = LendNoUtils.getLendItemNo();
        lendItem.setLendItemNo(lendItemNo);
        lendItem.setLendId(lend.getId());
        lendItem.setInvestUserId(userId);

        lendItem.setInvestName(investVo.getInvestName());

        lendItem.setInvestAmount(investAmount);
        lendItem.setLendYearRate(lend.getLendYearRate());
        lendItem.setInvestTime(LocalDateTime.now());
        lendItem.setLendStartDate(lend.getLendStartDate());
        lendItem.setLendEndDate(lend.getLendEndDate());
        BigDecimal interestCount = lendService.getInterestCount(
                investAmount,
                lend.getLendYearRate(),
                lend.getPeriod(),
                lend.getReturnMethod());
        lendItem.setExpectAmount(interestCount);

        lendItem.setStatus(0);
        baseMapper.insert(lendItem);


        HashMap<String, Object> mapParam = new HashMap<>(15);

        mapParam.put("agentId", HfbConst.AGENT_ID);


        //投资人绑定协议号
        mapParam.put("voteBindCode", userBindMapper.getBindCodeByUserId(userId));

        //借款人绑定协议号
        mapParam.put("benefitBindCode", userBindMapper.getBindCodeByUserId(lend.getUserId()));

        //项目编号
        mapParam.put("agentProjectCode", lend.getLendNo());

        //项目名称
        mapParam.put("agentProjectName", lend.getTitle());

        mapParam.put("agentBillNo", lendItemNo);

        mapParam.put("voteAmt", investAmount);

        mapParam.put("votePrizeAmt", new BigDecimal(0));

        mapParam.put("voteFeeAmt", new BigDecimal(0));

        //项目总额
        mapParam.put("projectAmt", lend.getAmount());

        mapParam.put("note", "无");
        mapParam.put("notifyUrl", HfbConst.INVEST_NOTIFY_URL);
        mapParam.put("returnUrl", HfbConst.INVEST_RETURN_URL);
        mapParam.put("timestamp", RequestHelper.getTimestamp());
        mapParam.put("sign", RequestHelper.getSign(mapParam));


        return FormHelper.buildForm(HfbConst.INVEST_URL, mapParam);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String notify(Map<String, Object> paramMap) {
        log.info("投标成功");

        //获取投资编号
        String agentBillNo = paramMap.get("agentBillNo").toString();
        //判断流水
        if (transFlowService.isTransFlow(agentBillNo)) {
            log.warn("不能重复提交流水");
            return "fail";
        }
        //修改账户金额

        //获取用户的绑定协议号
        String bindCode = paramMap.get("voteBindCode").toString();

        //投资金额
        BigDecimal voteAmt = new BigDecimal(paramMap.get("voteAmt").toString());
        BigDecimal prizeAmt = new BigDecimal(paramMap.get("votePrizeAmt").toString());
        BigDecimal amount = voteAmt.subtract(prizeAmt).negate();


        userAccountMapper.updateAccount(bindCode, amount, voteAmt);

        //修改投资记录的投资状态改为已支付
        QueryWrapper<LendItem> lendItemQueryWrapper = new QueryWrapper<>();
        lendItemQueryWrapper.eq("lend_item_no", agentBillNo);
        LendItem lendItem = baseMapper.selectOne(lendItemQueryWrapper);
        lendItem.setStatus(1);
        baseMapper.updateById(lendItem);

        //修改标的信息：投资人数、已投金额
        Lend lend = lendService.getById(lendItem.getLendId());
        lend.setInvestNum(lend.getInvestNum() + 1);
        lend.setInvestAmount(lend.getInvestAmount().add(voteAmt));
        lendService.updateById(lend);


        //生成流水
        TransFlowBO transFlowBO = new TransFlowBO();
        transFlowBO.setMemo(paramMap.get("resultMsg").toString());
        transFlowBO.setAmount(amount);
        transFlowBO.setBindCode(bindCode);
        transFlowBO.setTransTypeEnum(TransTypeEnum.INVEST_LOCK);
        transFlowBO.setAgentBillNo(agentBillNo);
        transFlowService.saveTransFlow(transFlowBO);

        return "success";
    }

    @Override
    public List<LendItem> selectByLendId(Long lendId, Integer status) {
        QueryWrapper<LendItem> queryWrapper = new QueryWrapper();
        queryWrapper.eq("lend_id", lendId);
        queryWrapper.eq("status", status);
        List<LendItem> lendItemList = baseMapper.selectList(queryWrapper);
        return lendItemList;
    }

    @Override
    public List<LendItem> listByLendId(Long lendId) {
        QueryWrapper<LendItem> lendItemQueryWrapper = new QueryWrapper<>();
        lendItemQueryWrapper.eq("lend_id",lendId);

        return  baseMapper.selectList(lendItemQueryWrapper);
    }
}
